package com.luo.sc.oidc.authserver.handler.login;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Map;

/**
 * 通用登录 - 用户查询及认证服务 - 账号、密码验证的默认实现<br/>
 * 注：兼容原Spring Security UserDetailsService实现
 *
 * @author luohq
 * @version 1.0.0
 * @date 2022-03-03
 */
public class UniLoginUserDetailsPasswordMatcherService implements UniLoginUserDetailsService {
    /**
     * 登录表单常量定义
     */
    private static final String USERNAME_PARAMETER = "username";
    private static final String PASSWORD_PARAMETER = "password";

    /**
     * Spring Security UserDetailsService实现
     */
    private UserDetailsService userDetailsService;
    /**
     * 密码编码器
     */
    private PasswordEncoder passwordEncoder;

    public UniLoginUserDetailsPasswordMatcherService(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        this.userDetailsService = userDetailsService;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public UniLoginUserDetails loadUserByAuthParams(Map<String, String> authParams) throws UsernameNotFoundException {
        //验证账号、密码相关表单参数非空
        if (!authParams.containsKey(USERNAME_PARAMETER) || !authParams.containsKey(PASSWORD_PARAMETER)) {
            throw new UsernameNotFoundException("用户名或密码为空");
        }
        //获取用户名参数
        String username = authParams.get(USERNAME_PARAMETER);

        //调用SpringSecurity UserDetailsService查询用户
        UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

        //转换SpringSecurity UserDetails为UniLoginUserDetails
        return new UniLoginUserDetails(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities(), null);
    }


    @Override
    public void authenticateUser(Map<String, String> authParams, UniLoginUserDetails uniLoginUserDetails) throws AuthenticationException {
        //比较密码是否一致
        Boolean passwordMatch = this.passwordEncoder.matches(authParams.get(PASSWORD_PARAMETER), uniLoginUserDetails.getPassword());
        //若不一致，则抛出异常
        if (!passwordMatch) {
            throw new BadCredentialsException("密码不正确");
        }
    }

}
